
import com.googlecode.javacpp.FloatPointer;
import java.awt.Point;
import javax.swing.JFrame;
import com.googlecode.javacpp.Pointer;
import com.googlecode.javacv.*;
import static com.googlecode.javacv.cpp.opencv_core.*;
import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import static com.googlecode.javacv.cpp.opencv_highgui.*;

/**
 * C to Java translation of the houghlines.c sample provided in the c sample directory of OpenCV 2.1,
 * using the JavaCV Java wrapper of OpenCV 2.2 developped by Samuel Audet.
 *
 * @author Jeremy Nicola
 * jeremy.nicola@gmail.com
 */
public class HoughLines {

    /**
     * usage: java HoughLines imageDir\imageName TransformType
     */
    public static void main(String[] args) {

        String fileName = args.length >= 1 ? args[0] : "c:\\pizza3.jpg"; // if no params provided, compute the defaut image
        IplImage src = cvLoadImage(fileName, 0);
        IplImage dst;
        IplImage colorDst;
        CvMemStorage storage = cvCreateMemStorage(0);
        CvSeq lines = new CvSeq();
        cvSmooth(src, src, CV_GAUSSIAN, 9, 9, 1, 1);
        CanvasFrame source = new CanvasFrame("Source");
        CanvasFrame hough = new CanvasFrame("Hough");
        if (src == null) {
            System.out.println("Couldn't load source image.");
            return;
        }

        dst = cvCreateImage(cvGetSize(src), src.depth(), 1);
        colorDst = cvCreateImage(cvGetSize(src), src.depth(), 3);

        cvCanny(src, dst, 100, 300, 3);
        cvCvtColor(dst, colorDst, CV_GRAY2BGR);

        /*
         * apply the probabilistic hough transform
         * which returns for each line deteced two points ((x1, y1); (x2,y2))
         * defining the detected segment
         */
        if (args.length == 2 && args[1].contentEquals("probabilistic")) {
            System.out.println("Using the Probabilistic Hough Transform");
            lines = cvHoughLines2(dst, storage, CV_HOUGH_PROBABILISTIC, 1, Math.PI / 180, 40, 50, 10);
            for (int i = 0; i <= lines.total(); i++) {
                // from JavaCPP, the equivalent of the C code:
                // CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
                // CvPoint first=line[0], second=line[1]
                // is:
                // CvPoint first=line.position(0), secon=line.position(1);

                Pointer line = cvGetSeqElem(lines, i);
                CvPoint pt1 = new CvPoint(line).position(0);
                CvPoint pt2 = new CvPoint(line).position(1);
                System.out.println("Line spotted: ");
                System.out.println("\t pt1: " + pt1);
                System.out.println("\t pt2: " + pt2);
                cvLine(colorDst, pt1, pt2, CV_RGB(255, 0, 0), 3, CV_AA, 0); // draw the segment on the image
            }
        } /*
         * Apply the multiscale hough transform which returns for each line two float parameters (rho, theta)
         * rho: distance from the origin of the image to the line
         * theta: angle between the x-axis and the normal line of the detected line
         */ else if (args.length == 2 && args[1].contentEquals("multiscale")) {
            System.out.println("Using the multiscale Hough Transform"); //
            lines = cvHoughLines2(dst, storage, CV_HOUGH_MULTI_SCALE, 1, Math.PI / 180, 40, 1, 1);
            for (int i = 0; i < lines.total(); i++) {
                CvPoint2D32f point = new CvPoint2D32f(cvGetSeqElem(lines, i));
                float rho = point.x();
                float theta = point.y();
                double a = Math.cos((double) theta), b = Math.sin((double) theta);
                double x0 = a * rho, y0 = b * rho;
                CvPoint pt1 = new CvPoint((int) Math.round(x0 + 1000 * (-b)), (int) Math.round(y0 + 1000 * (a))), pt2 = new CvPoint((int) Math.round(x0 - 1000 * (-b)), (int) Math.round(y0 - 1000 * (a)));
                System.out.println("Line spoted: ");
                System.out.println("\t rho= " + rho);
                System.out.println("\t theta= " + theta);
                //  cvLine(colorDst, pt1, pt2, CV_RGB(255, 0, 0), 3, CV_AA, 0);
            }
        } /*
         * Default: apply the standard hough transform. Outputs: same as the multiscale output.
         */ else {
            System.out.println("Using the Standard Hough Transform");
            lines = cvHoughLines2(dst, storage, CV_HOUGH_STANDARD, 1, Math.PI / 180, 90, 0, 0);
            //    circle = cvHoughCircles(src, dst, CV_HOUGH_GRADIENT, CV_C, CV_L1, CV_L2, CV_C, CV_L1, CV_L2);
            //   circle = cvHoughCircles(src, storage, CV_C, CV_C, CV_L1, CV_L2, CV_C, CV_L1, CV_L2);
            /*  for (int i = 0; i < lines.total(); i++) {
            CvPoint2D32f point = new CvPoint2D32f(cvGetSeqElem(lines, i));
            
            float rho=point.x();
            float theta=point.y();
            
            double a = Math.cos((double) theta), b = Math.sin((double) theta);
            double x0 = a * rho, y0 = b * rho;
            CvPoint pt1 = new CvPoint((int) Math.round(x0 + 1000 * (-b)), (int) Math.round(y0 + 1000 * (a))), pt2 = new CvPoint((int) Math.round(x0 - 1000 * (-b)), (int) Math.round(y0 - 1000 * (a)));
            System.out.println("Line spotted: ");
            System.out.println("\t rho= " + rho);
            System.out.println("\t theta= " + theta);
            cvLine(colorDst, pt1, pt2, CV_RGB(255, 0, 0), 3, CV_AA, 0);
            }*/
            /*   for (int i = 0; i <= lines.total(); i++) {
            // from JavaCPP, the equivalent of the C code:
            // CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
            // CvPoint first=line[0], second=line[1]
            // is:
            // CvPoint first=line.position(0), secon=line.position(1);
            Pointer line = cvGetSeqElem(lines, i);
            CvPoint pt1 = new CvPoint(line).position(0);
            CvPoint pt2 = new CvPoint(line).position(1);
            System.out.println("Line spotted: ");
            System.out.println("\t pt1: " + pt1);
            System.out.println("\t pt2: " + pt2);
            cvLine(colorDst, pt1, pt2, CV_RGB(255, 0, 0), 3, CV_AA, 0); // draw the segment on the image
            }*/
            //    CvSeq results = cvHoughCircles(src,storage, CV_HOUGH_GRADIENT, 1, 7, 1, 1, 2, 4);
            CvSeq circle = cvHoughCircles(dst, storage, CV_HOUGH_GRADIENT, 1, 600, CV_L2, CV_C, 200, 200);
          //  cvHoughCircles(src, dst, CV_C, CV_C, CV_L1, CV_L2, CV_C, CV_L1, CV_L2)
            CvPoint pt;

            System.out.println(circle.total());
            for (int i = 0; i < circle.total(); i++) {
                //  System.out.println(cvGetSeqElem(results, CV_C).asBuffer().toString());
                //      p = cvGetSeqElem(results, i));
                //     pt = cvPoint(Math.round(p[0]), Math.round(p[1]));
                //     cvCircle(imageGray, pt.byValue(), Math.round(p[2]),
                //  CV_RGB(
                //  0xff, 0xFF, 0xFF).byValue(), 1, 8, 0);
                //   CvPoint2D32f p = new CvPoint2D32f(cvGetSeqElem(circle, i));
                /*
                Pointer circle1 = cvGetSeqElem(circle, i);
                System.out.println(circle1);
                 */
                CvPoint3D32f point = new CvPoint3D32f(cvGetSeqElem(circle, i));
                CvPoint center = new CvPoint(Math.round(point.x()), Math.round(point.y()));
                cvCircle(colorDst, center, Math.round(point.z()), CvScalar.GREEN, 3, 8, 0);
                System.out.println(center.toString());
            }
        }
        source.showImage(src);
        hough.showImage(colorDst);
        source.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        hough.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    }
}
